'use strict'

require('log-timestamp');
const model = require('../models/models');
const User = model.user;
const Comment = model.comment;
const Moment = model.momentResource;
const Video = model.videoResource;
const Broadcast = model.broadcastResource;
const Favourite = model.favourite;
const AddressBook = model.addressBook;
const assert = require('assert');
const Gift = model.gift;
const asyncMethod = require('async');
const debug = true;
const utils = require('../utils/utils');
const isTest = false;
const Map = require('immutable');
// const {Map} = require('immutable');

/**
 * no matter found or not just return
 * the caller must handle
 * @param {*} token
 */
function userFind(findType, value) {
  return new Promise(function(resolve, reject) {
    switch(findType) {
      case 'uuid':
        User.findOne({userCode: value}, (err, user) => {
          if(err) reject(err.message);
          else resolve(user)
        })
        break;
      case 'token':
        User.findOne({token: value}, (err, user) => {
          if(err) reject(err.message);
          else resolve(user)
        })
        break;
      default:
        console.error('wrong findby type');
    }
  }).catch(err => {
    console.error(err);
  })
}


/**
 * no matter found or not just return
 * the caller must handle
 * @param {*} mobile
 */
function userFind_email(email) {
  return new Promise(function(resolve, reject) {
    if(!email) reject('wrong email address');
    else
      User.findOne({email: email}, (err, user) => {
        if(err) reject(err.message)
        else resolve(user)
      })
  }).catch(err => {
    console.error(err)
  })
}
function userFind_mobile(mobile, countryCode) {
  return new Promise(function(resolve, reject) {
    if(!mobile || !countryCode) reject('wrong mobile or countryCode');
    else
      User.findOne({mobile: mobile, countryCode: countryCode}, (err, user) => {
        if(err) reject(err.message)
        else resolve(user)
      })
  }).catch(err => {
    console.error(err)
  })
}


/**
 * no matter found or not just return
 * the caller must handle
 * @param {*} userCode
 */
function addressBookUserFind(userCode) {
  return new Promise(function(resolve, reject) {
    if(!mobile) reject(undefined);
    else
      AddressBook.findOne({userCode: userCode}, (err, user) => {
        if(err)
          reject(err.message);
        else
          resolve(user)
      })
  }).catch(err => {
    console.error(err);
  })
}

/**
 * no matter found or not just return
 * the caller must handle
 * @param {*} token
 */
function userFind_token(token) {
  return new Promise(function(resolve, reject) {
    if(!token) resolve(undefined);
    else
      User.findOne({token: token}, (err, user) => {
        if(err)
          reject(err.message);
        else
          resolve(user)
      })
  }).catch(err => {
    console.error(err);
  })
}

/**
 *  * no matter found or not just return
 * the caller must handle
 * try userCode first and then token
 * @param token
 * @param userCode
 * @returns {Promise<any>}
 */
function userFind_token_userCode(token, userCode) {
  return new Promise(function(resolve, reject) {
    if(!token && !userCode) reject(undefined);
    else if(userCode){
      User.findOne({"userCode": userCode}, (err, user) => {
        if(err){
          reject(err.message);
        }
        else {
          if(user && user.token != token){
            reject('not authorized');
          }
          else if(!user.isEnabled) reject('user is not enabled');
          else {
            resolve(user);
          }
        }
      })
    }
    else {
      User.findOne({"token": token}, (err, user) => {
        if(err)
          reject(err.message);
        else if(!user)
          reject('not authorized');
        else
          resolve(user)
      })
    }
  }).catch()
}

function userFind_token_userCode_auth(token, userCode) {
  return new Promise(function(resolve, reject) {
    if(!token && !userCode) reject(undefined);
    else if(userCode){
      User.findOne({"userCode": userCode}, (err, user) => {
        if(err){
          reject(err.message);
        }
        else {
          if(!user || user.token != token) reject('not authorized');
          else if(!user.isEnabled) reject('user diabled');
          else resolve(user);
        }
      })
    }
    else {
      User.findOne({"token": token}, (err, user) => {
        if(err)
          reject(err.message);
        else if(!user) reject('not authorized');
        else if(!user.isEnabled) reject('user diabled');
        else resolve(user);
      })
    }
  }).catch()
}

function userFind_openid(openid) {
  return new Promise(function(resolve, reject) {
    if(!openid) reject(undefined);
    else
      User.findOne({"wechat.openid": openid}, (err, user) => {
        if(err) reject(err.message);
        else if(user && !user.isEnabled) reject('user diabled')
        else resolve(user)
      })
  }).catch(err => {
    console.error(err);
  })
}

/**
 * find the user by userCode
 * @param userCode
 * @return {Promise<any | never>}
 */
function userFind_userCode(userCode) {
  return new Promise(function(resolve, reject) {
    if(!userCode) resolve(undefined);
    else
      User.findById(userCode, (err, user) => {
        if(err) reject(err.message);
        else resolve(user)
      })
  }).catch()
}

/**
 * the user must exist or reject
 * @param {String} token
 */
function userFindAuth(token, userCode) {
  return new Promise(function(resolve, reject) {
    if(!userCode && !token) reject('token & userCode empty')
    if(userCode)
      User.findOne({userCode: userCode}, (err, user) => {
        if(err) reject(err.message);
        else {
          if(!user) reject('user not found @userCode=' + userCode);
          else if(!user.isEnabled) reject('user is not enabled');
          else resolve(user)
        }
      })
    else
      User.findOne({token: token}, (err, user) => {
        if(err) reject(err.message);
        else {
          if(!user) reject('user not found @token=' + token);
          else resolve(user)
        }
      })
  }).catch(err => {
  })
}

/**
 *
 * @param {String} token
 */
function userAuth(token) {
  return new Promise(function(resolve, reject) {
    User.findOne({token: token}, {userCode: 1}, (err, user) => {
      if(err || !user)
        reject('not authorized');
      else if(!user.isEnabled) reject('user is not enabled');
      else {
        resolve()
      }
    })
  })
}

/**
 *
 * @param {String} resourceId
 */
function favouritebyResourceId(resourceId) {
  return new Promise(function(resolve, reject) {
    Favourite.findOne({resourceId: resourceId}, (err, fav) => {
      if(err) reject(err.message)
      else resolve(fav)
    })
  }).catch(err => {
    console.error(err);
  })
}

/**
 *
 * @param {String} resourceId
 */
function momentbyResourceId(resourceId) {
  return new Promise(function(resolve, reject) {
    Moment.findOne({
      resourceId: resourceId
    }, (err, moment) => {
      if(err) reject(err.message)
      else resolve(moment)
    })

  }).catch(err => {
    console.error(err);
  })
}

/**
 *
 * @param {String} resourceId
 */
function momentbyUserCode(userCode) {
  return new Promise(function(resolve, reject) {
    Moment.find({
      userCode: userCode
    }, (err, moments) => {
      if(err)
        reject(err.message)
      else
        resolve(moments)
    })
  }).catch(err => {
    console.error(err);
  })
}

/**
 *
 * @param {String} resourceId
 */
function resourceFind_zl(resourceId) {
  return new Promise(function(resolve, reject) {
    if(!resourceId){
      return resolve(undefined)
    }
    var _resourceType;
    if(resourceId.indexOf('moment') >= 0){
      _resourceType = Moment;
    }
    else if(resourceId.indexOf('video') >= 0){
      _resourceType = Video;
    }
    else if(resourceId.indexOf('broadcast') >= 0){
      _resourceType = Broadcast;
    }
    else {
      console.error('err511: wrong resource type');
      return 'wrong resource type'
    }
    _resourceType.findOne({resourceId: resourceId}, (err, resource) => {
      if(err || !resource)
        reject('resource not found or database error')
      else
        resolve(resource)
    })

  }).catch(err => {
    console.error(err);
  })
}


/**
 *
 * @param {String} resourceId
 */
function resourceFind(resourceType, value) {
  return new Promise(function(resolve, reject) {
    if(!resourceType || !value){
      return resolve(undefined)
    }
    var _resourceType;
    switch(resourceType) {
      case 'moment':
        _resourceType = Moment;
        break;
      case 'video':
        _resourceType = Video;
        break;
      case 'broadcast':
        _resourceType = Broadcast;
        break;
      default:
        console.error('err511: wrong resource type');
        return 'wrong resource type'
    }
    _resourceType.findOne({resourceId: value}, (err, resource) => {
      if(err || !resource)
        reject('resource not found or database error')
      else
        resolve(resource)
    })

  }).catch(err => {
    console.error(err);
  })
}

function resourceFind_new(resourceModel, resourceId) {
  return new Promise(function(resolve, reject) {
    if(!resourceModel || !resourceId){
      return resolve(undefined)
    }
    resourceModel.findOne({resourceId: resourceId}, (err, resource) => {
      if(err || !resource)
        reject('resource not found or database error')
      else
        resolve(resource)
    })
  }).catch(err => {
    console.error(err);
  })
}

/**
 *
 * @param {String} resourceType
 */
function resourcelistFind(resourceType) {
  return new Promise(function(resolve, reject) {
    if(!resourceType){
      return reject(undefined)
    }
    var _resourceType;
    switch(resourceType) {
      case 'moment':
        _resourceType = Moment;
        break;
      case 'video':
        _resourceType = Video;
        break;
    }
    _resourceType.find({}, (err, resource) => {
      if(err || !resource) reject('resourcce not find or db wrong')
      else resolve(resource)
    })

  }).catch(err => {
    console.error(err);
  })
}

function resourceListbyUserCode(resourceType, userCode) {
  var _resourceType;
  switch(resourceType.toLowerCase()) {
    case 'moment':
      _resourceType = Moment;
      break;
    case 'video':
      _resourceType = Video;
      break;
    case 'broadcast':
      _resourceType = Broadcast;
      break;
    default:
      console.error('err5072: wrong resource type');
      return 'wrong resource type'
  }
  return new Promise(function(resolve, reject) {
    _resourceType.find({userCode: userCode},
      function(err, resourceList) {
        if(err) reject(err.message)
        else resolve(resourceList)
      })

  }).catch(err => {
    console.error(err);
  })
}

function commentFindOne(commentId) {
  return new Promise(function(resolve, reject) {
    if(!commentId){
      resolve(undefined);
    }
    else {
      Comment.findOne({commentId: commentId}, (err, comment) => {
        if(err){
          reject(err.message);
        }
        else {
          if(!comment)
            reject('comment not found by commentId:' + commentId);
          else
            resolve(comment);
        }
      })
    }
  }).catch(err => {
    console.error(err);
  });
}

/**
 *
 * @param creator
 * @param resourceId 该参数和commentId只能出现一个
 * @param commentId
 * @returns {Promise<any>}
 */
function getCommentlist_new(creator, resourceId, commentId) {
  return new Promise(function(resolve, reject) {
    var childs = [];
    var findComments = Comment.find({resourceId: resourceId})
      .exec()
    assert.ok(findComments instanceof Promise);

    findComments.then(function(comments) {
      if(comments.length <= 0){
        resolve([]);
        return;
      }
      //取出所有的父辈节点和子节点
      // var childs = [];
      var parents = [];
      if(!commentId){
        //一级评论。针对资源（图文，视频）的评论
        for(let i in comments) {
          let cmt = comments[i];
          if(!cmt.parentId){
            parents.push(cmt)
          }
          else {
            childs.push(cmt)
          }
        }
      }
      else {
        //二级评论。针对评论的评论
        for(let i in comments) {
          let cmt = comments[i];
          if(cmt.commentId == commentId){
            //父节点只有本尊
            parents.push(cmt)
          }
          else {
            if(cmt.parentId == commentId){
              //父节点指向本尊的都是子节点
              childs.push(cmt)
            }
          }
        }
      }
      if(!parents || parents.length <= 0){
        reject('fetch comments failure')
        return;
      }

      //遍历所有的父节点
      var retDataArray = [];
      parents.forEach(current_comment => {
        var d = getResData_new(creator, current_comment, err => {
          if(err) throw err;
        });
        // retDataArray.sort(function (a, b) {
        //   return Number(a.uploadTime) - Number(b.uploadTime);
        // });
        retDataArray = retDataArray.concat(d);
      })
      if(commentId){
        data.shift();
      }

      resolve(retDataArray)

    }).catch(err => {
      console.error(err);
    })

    /**拼装数据
     * recursively get the return data for comment
     * it's construct as comment/childs count
     * @param {*} comment
     */
    function getResData_new(comment) {
      try {
        var retData = [];
        let data = {
          body: comment.body,
          creator: comment.creator || {},
          postTime: comment.postTime,
          replyTo: comment.replyTo,
          replyToName: comment.replyToName,
          commentId: comment.commentId,
          likeCount: comment.likes.length
        };
        // let data = JSON.parse(JSON.stringify(comment));
        // let data = new Comment({});
        // data.creator = comment.creator || {};
        if(!comment.childrenIds || comment.childrenIds.length == 0){
          data.comments = [];
        }
        else {
          let childComments = commentIdstoComments(comment.childrenIds);
          if(childComments.length <= 0){
            return;
          }
          var childData = [];
          childComments.forEach(childComment => {
            childData = childData.concat(getResData_new(childComment));
          })
          data.comments = childData;
        }
        retData.push(data);
      } catch(e) {
        console.error(e);
      }
      return retData;
    }

    function getResData_new1(creator, comment) {
      try {
        var retData = [];
        // let data = {
        //   body: comment.body,
        //   // creator: getCreator_nopromise(creator),
        //   creator: comment.creator,
        //   postTime: comment.postTime,
        //   replyTo: comment.replyTo,
        //   replyToName: comment.replyToName,
        //   commentId: comment.commentId,
        //   likeCount: comment.likes.length
        // };
        let data = JSON.parse(JSON.stringify(comment));
        if(!comment.childrenIds || comment.childrenIds.length == 0){
          data.comments = [];
        }
        else {
          let childComments = commentIdstoComments(comment.childrenIds);
          if(childComments.length <= 0){
            return;
          }
          var childData = [];
          childComments.forEach(childComment => {
            childData = childData.concat(getResData_new(creator, childComment));
          })
          data.comments = childData;
        }
        retData.push(data);
      } catch(e) {
        console.error(e);
      }
      return retData;
    }

    /**
     * convert the child id list into comment list
     * @param {*} IdList commentId list
     */
    function commentIdstoComments(IdList) {
      let retval = [];
      childs.forEach(c => {
        IdList.forEach(id => {
          if(id == c.commentId){
            retval.push(c);
          }
        })
      })
      return retval;
    }
  })
}

function getCommentlist_nopromise_v1127(m_resource, commentId) {
  let isSndComment = (commentId && commentId.length > 5);
  if(!isSndComment && !m_resource) return;
  let allComments = m_resource.get('commentList');
  if(!allComments)
    return;
  else if(allComments.length <= 0)
    return [];

  /**
   * recursively get the return data for comment
   * it's construct as comment/childs count
   * @param {*} comment
   */
  function getResData(comment) {
    if(false && comment.commentId == 'moment-5bfa9ecc69c8b82b3192a947'){
      console.log(comment);
    }
    var retData = [];
    let data = {
      body: comment.body,
      creator: comment.creator,
      postTime: comment.postTime,
      replyTo: comment.replyTo,
      replyToName: comment.replyToName,
      commentId: comment.commentId,
      likeCount: comment.likes.length
    };
    if(!comment.childrenIds || comment.childrenIds.length == 0){
      data.comments = [];
    }
    else {
      let childComments = commentIdstoComments(comment.childrenIds);
      let childData = [];
      childComments.forEach(childComment => {
        childData = childData.concat(getResData(childComment));
      })
      data.comments = childData;
    }
    retData.push(data);
    return retData;
  }

  /**
   * convert the child id list into comment list
   * @param {*} IdList commentId list
   */
  function commentIdstoComments(IdList) {
    let retval = [];
    childComments.forEach(c => {
      IdList.forEach(id => {
        if(id == c.commentId){
          retval.push(c);
        }
      })
    })
    return retval;
  }

  let parentComments = [];
  let childComments = [];
  /**
   * 分离 "一级评论parentComments" 和 "二级评论childComments"
   */
  if(!isSndComment){
    for(let i in allComments) {
      let cmt = allComments[i];
      if(!cmt.parentId){
        parentComments.push(cmt)
      }
      else {
        childComments.push(cmt)
      }
    }
  }
  else {
    for(let i in allComments) {
      let cmt = allComments[i];
      if(cmt.commentId == commentId){
        parentComments.push(cmt)
      }
      else {
        if(cmt.parentId == commentId){
          childComments.push(cmt)
        }
      }
    }
  }

  var retDataArray = [];
  parentComments.forEach(comment => {
    //递归组合返回"评论"数据
    var d = getResData(comment, err => {
      if(err) throw err;
    });

    // retDataArray.sort(function (a, b) {
    //   return Number(a.uploadTime) - Number(b.uploadTime);
    // });

    retDataArray = retDataArray.concat(d);
  })

  /*if(commentId){
    data.shift();
  }*/

  return retDataArray;

}

function getCommentlist_nopromise(resource, commentId) {
  let isSndComment = (commentId && commentId.length > 5);
  if(!isSndComment && !resource) return;
  let allComments = resource.commentList;
  if(!allComments)
    return;
  else if(allComments.length <= 0)
    return [];

  /**
   * recursively get the return data for comment
   * it's construct as comment/childs count
   * @param {*} comment
   */
  function getResData(comment) {
    var retData = [];
    let data = {
      body: comment.body,
      creator: comment.creator,
      postTime: comment.postTime,
      replyTo: comment.replyTo,
      replyToName: comment.replyToName,
      commentId: comment.commentId,
      likeCount: comment.likes.length
    };
    if(!comment.childrenIds || comment.childrenIds.length == 0){
      data.comments = [];
    }
    else {
      // let childComments = commentIdstoComments(comment.childrenIds);

      let childComments = [];
      childComments.forEach(c => {
        IdList.forEach(id => {
          if(id == c.commentId){
            childComments.push(c);
          }
        })
      })

      let childData = [];
      childComments.forEach(childComment => {
        childData = childData.concat(getResData(childComment));
      })
      data.comments = childData;
    }
    retData.push(data);
    return retData;
  }

  /**
   * convert the child id list into comment list
   * @param {*} IdList commentId list
   */
  /*function commentIdstoComments(IdList) {
    let retval = [];
    childComments.forEach(c => {
      IdList.forEach(id => {
        if(id == c.commentId){
          retval.push(c);
        }
      })
    })
    return retval;
  }*/

  let parentComments = [];
  let childComments = [];
  /**
   * 分离 "一级评论parentComments" 和 "二级评论childComments"
   */
  if(!isSndComment){
    for(let i in allComments) {
      let cmt = allComments[i];
      if(!cmt.parentId){
        parentComments.push(cmt)
      }
      else {
        childComments.push(cmt)
      }
    }
  }
  else {
    for(let i in allComments) {
      let cmt = allComments[i];
      if(cmt.commentId == commentId){
        parentComments.push(cmt)
      }
      else {
        if(cmt.parentId == commentId){
          childComments.push(cmt)
        }
      }
    }
  }

  var retDataArray = [];
  parentComments.forEach(comment => {
    //递归组合返回"评论"数据
    var d = getResData(comment, err => {
      if(err) throw err;
    });

    // retDataArray.sort(function (a, b) {
    //   return Number(a.uploadTime) - Number(b.uploadTime);
    // });

    retDataArray = retDataArray.concat(d);
  })

  /*if(commentId){
    data.shift();
  }*/

  return retDataArray;

}

function getCommentlist(resourceId, commentId) {
  return new Promise(function(resolve, reject) {
    var childs = [];
    var findComments = Comment.find({resourceId: resourceId})
      .exec()
    assert.ok(findComments instanceof Promise);

    findComments.then(function(comments) {
      if(comments.length <= 0){
        resolve([]);
        return;
      }
      var parents = [];
      if(!commentId){
        for(let i in comments) {
          let cmt = comments[i];
          if(!cmt.parentId){
            parents.push(cmt)
          }
          else {
            childs.push(cmt)
          }
        }
      }
      else {
        for(let i in comments) {
          let cmt = comments[i];
          if(cmt.commentId == commentId){
            parents.push(cmt)
          }
          else {
            if(cmt.parentId == commentId){
              childs.push(cmt)
            }
          }
        }
      }

      if(!parents || parents.length <= 0){
        reject('fetch comments failure')
        return;
      }

      var retDataArray = [];
      parents.forEach(current_comment => {
        var d = getResData(current_comment, err => {
          if(err) throw err;
        });
        // retDataArray.sort(function (a, b) {
        //   return Number(a.uploadTime) - Number(b.uploadTime);
        // });
        retDataArray = retDataArray.concat(d);
      })
      if(commentId){
        data.shift();
      }

      resolve(retDataArray)

    }).catch(err => {
      console.error(err);
    })

    /**
     * recursively get the return data for comment
     * it's construct as comment/childs count
     * @param {*} comment
     */
    function getResData(comment, error) {
      var retData = [];
      let data = {
        body: comment.body,
        creator: comment.creator,
        postTime: comment.postTime,
        replyTo: comment.replyTo,
        replyToName: comment.replyToName,
        commentId: comment.commentId,
        likeCount: comment.likes.length
      };
      if(!comment.childrenIds || comment.childrenIds.length == 0){
        data.comments = [];
      }
      else {
        let childComments = commentIdstoComments(comment.childrenIds);
        var childData = [];
        childComments.forEach(childComment => {
          childData = childData.concat(getResData(childComment));
        })
        data.comments = childData;
      }
      retData.push(data);
      return retData;
    }

    /**
     * convert the child id list into comment list
     * @param {*} IdList commentId list
     */
    function commentIdstoComments(IdList) {
      let retval = [];
      childs.forEach(c => {
        IdList.forEach(id => {
          if(id == c.commentId){
            retval.push(c);
          }
        })
      })
      return retval;
    }
  })
}

function commentsbyResourceId(resourceId) {
  return new Promise(function(resolve, reject) {
    Comment.find({resourceId: resourceId}, (err, comments) => {
      if(err)
        reject(err.message)
      else
        resolve(comments)
    })
  }).catch(err => {
    console.error(err);
  });
}

/**
 * find all my followed netcaster profile and broadcast info
 * may change on demand from app developer
 * @param {String} user
 */
function followingUserList(me) {
  return new Promise(function(resolve, reject) {
    var followingUsers = [];
    asyncMethod.each(me.following, function(userCode, callback) {
      User.find({userCode: userCode}, function(err, user) {
        if(err){
          reject(err.message)
        }
        else {
          followingUsers.push(user);
          callback(null);
        }
      })
    }, function(err) {
      if(err){
        reject(err.message)
      }
      else {
        resolve(followingUsers)
      }
    })
  }).catch(err => {
    console.error('followedNetcasterList,err:%s', err)
  })
}

/**
 * 根据礼物id获取礼物对象
 */
function giftFind_id(id) {
  return new Promise(function(resolve, reject) {
    Gift.findOne({giftid: id}, (err, gift) => {
      if(err) reject(err.message);
      else resolve(gift)
    })
  }).catch(err => {
    console.error('err502:' + err);
  });
}

function getNetCastData(theUser) {
  var data = {
    //用户数据
    userCode: theUser.userCode,
    name: theUser.name,
    nickname: theUser.nickName,
    gender: theUser.gender,
    interests: theUser.interests,
    avatar: theUser.avatar ? theUser.avatar : model.emptyAvatar,
    //直播信息
    preview: theUser.publishedResources.preview,
    resourceUri: theUser.publishedResources.resourceUri,
    title: theUser.publishedResources.title,
    tags: theUser.publishedResources.tags,
    id: theUser.publishedResources.id,
    author: theUser.publishedResources.author,
    lat: theUser.publishedResources.lat,
    lon: theUser.publishedResources.lon,
    startTime: theUser.publishedResources.ofDates,
  };
  var coinAmt = 0;
  if(theUser.giftsReceived && theUser.giftsReceived.length > 1){
    for(let g in theUser.giftsReceived) {
      coinAmt += theUser.giftsReceived[g].price;
    }
  }
  data.coinAmount = coinAmt;
  //用户资源数据
  data.lon = theUser.publishedResources.lon;
  data.lat = theUser.publishedResources.lat;
  //
  data.coverImage = theUser.publishedResources.coverImage;
  data.description = theUser.publishedResources.description;
  data.channelId = theUser.publishedResources.channelId;
  data.ranking = theUser.publishedResources.ranking;
  data.commentCount = theUser.publishedResources.commentCount;
  data.followingCount = theUser.publishedResources.followingCount;
  data.faouriteCount = theUser.publishedResources.faouriteCount;
  data.likeCount = theUser.publishedResources.likeCount;
  data.audienceCount = (theUser.publishedResources.audiences) ? theUser.publishedResources.audiences.count : 1000;
  return data;
}

function getVideoResourceData(user, resourceList) {
  return new Promise(function(resolve, reject) {
    var videoCollection = [];
    asyncMethod.each(resourceList, function(video, callback) {
      var v_data = {
        resourceId: video.resourceId,
        category: video.category,
        uploadTime: video.uploadTime,
        likeCount: video.likes.length,
        favouriteCount: video.favourites.length,
        // likes: video.likes,
        isMyFavourite: isFavourite(video, user),
        isMyLike: isLike(video, user),
        resourceUri: video.resourceUri,
        preview: video.preview,
        favourites: video.favourites,
        shares: video.shares,
        comments: video.comments,
        tags: video.tags,
        music: video.music,
        fileSize: video.fileSize,
        title: video.title,
        description: video.description,
        lat: video.lat,
        lon: video.lon,
        permission: video.permission,
        type: 1
      }
      var comments = getCommentlist(video.resourceId);
      assert.ok(comments instanceof Promise);
      comments.then(value => {
        v_data.comments = value;
      })
      findCreator_by_resourceId(Video, video.resourceId)
        .then(function(creator) {
          v_data.creator = creator.getCreator_nopromise();
          videoCollection.push(v_data);
          callback(null);
        }).catch(err => {
        reject(err);
      })
    }, function(err) {
      if(err){
        reject(err);
      }
      resolve(videoCollection);
    })
  }).catch(err => console.error(e))
}

function getVideoResourceData_1024(user, resourceList) {
  var videoCollection = [];
  if(!resourceList || resourceList.length <= 0){
    return []
  }
  for(let j in resourceList) {
    var v = resourceList[j];
    var v_data = {
      resourceId: v.resourceId,
      category: v.category,
      uploadTime: v.uploadTime,
      likeCount: v.likeCount,
      likes: v.likes,
      resourceUri: v.resourceUri,
      preview: v.preview,
      favourites: v.favourites,
      shares: v.shares,
      comments: v.comments,
      tags: v.tags,
      music: v.music,
      fileSize: v.fileSize,
      title: v.title,
      description: v.description,
      lat: v.lat,
      lon: v.lon,
      permission: v.permission,
    }
    // var creator = {
    //   name: user.name ? user.name : '',
    //   nickname: user.nicName ? user.nicName : '',
    //   userCode: user.userCode,
    //   avatar: user.avatar ? user.avatar : model.emptyAvatar
    // }

    //v_data.creator = getCreator_nopromise(user); // 88888888
    findCreator_by_resourceId(Video, v.resourceId).then(function(creator) {

      v_data.creator = creator.getCreator_nopromise();

    }).catch(err => {
      res.json({errorCode: 0, message: err.message ? err.message : err})
    });


    // v_data.commentCount = v.comments.length;
    // v_data.followingCount = v.follower.length;
    v_data.favouriteCount = v.favourites.length;

    var comments = getCommentlist(v.resourceId);
    await
    comments;
    v_data.comments = comments;
    v_data.type = 1;
    videoCollection.push(v_data)
  }
  return videoCollection;
}


function getnetcastResourceData(followingUserList) {
  var netcastCollection = [];
  followingUserList.forEach(f_user => {
    netcastCollection.push(getNetCastData(f_user));
  })
  return netcastCollection;
}

function sendListPage_v1126(session, res) {
  try {
    if(!session || !session.dataList)
      throw 'no data to transfer'
    var dataListArray = [];
    var dataList = session.dataList;

    var lastIndex = (Number(session.pageSize) <= Number(session.dataList.length)) ?
      session.pageSize : session.dataList.length;
    for(var i = 0; i < lastIndex; i++) {
      dataListArray.push(dataList[i]);
    }
    for(var i = 0; i < lastIndex; i++) {
      (session.dataList).shift();
    }
    session.transferred++;
    var msg = 'pageSize=' + session.pageSize
      + '; pages sent=' + session.transferred + '; records remained=' + session.dataList.length;
    if(debug) console.log(msg);
    if(Number(session.dataList.length) > 0){
      res.json({errorCode: 1, message: msg, total: session.total, data: dataListArray});
    }
    else {
      if(debug) console.log(msg + '\tno more data left');
      res.json({errorCode: 1, message: msg, total: session.total, data: dataListArray});
    }
  } catch(e) {
    res.send({errorCode: 0, message: e.message || e});
  }
}
function sendListPage(req, res) {
  try {
    var dataListArray = [];
    var dataList = req.session.dataList;

    var lastIndex = (Number(req.session.pageSize) <= Number(req.session.dataList.length)) ?
      req.session.pageSize : req.session.dataList.length;
    for(let i = 0; i < lastIndex; i++) {
      dataListArray.push(dataList[i]);
    }
    for(let i = 0; i < lastIndex; i++) {
      (req.session.dataList).shift();
    }
    req.session.transferred++;
    var msg = 'total:'+req.session.total+ '; pageSize=' + req.session.pageSize
      + '; pages sent=' + req.session.transferred + '; records remained=' + req.session.dataList.length;
    if(debug) console.log(msg);
    // let commentCount = req.session.commentCount;
    // dataListArray.count = commentCount;
    // dataListArray.count = session.total;
    if(Number(req.session.dataList.length) > 0){
      res.json({errorCode: 1, message: msg, data: dataListArray});
      // res.json({ errorCode: 1, message: msg, commentCount: commentCount, data: dataListArray });
    }
    else {
      if(debug) console.log(msg + '\tno more data left');
      res.json({errorCode: 1, message: msg, data: dataListArray});
      // res.json({ errorCode: 1, message: msg, commentCount: commentCount, data: dataListArray });
      // req.session.destroy();
    }
  } catch(e) {
    console.error(e);
    res.status(500).send({errorCode: 5, message: e.message})
    // req.session.destroy();
  }
}

function sendListPage_obsolate(req, res) {
  try {
    var dataListArray = [];
    var dataList = req.session.dataList;

    var lastIndex = (Number(req.session.pageSize) <= Number(req.session.dataList.length)) ?
      req.session.pageSize : req.session.dataList.length;
    for(var i = 0; i < lastIndex; i++) {
      dataListArray.push(dataList[i]);
    }
    for(var i = 0; i < lastIndex; i++) {
      (req.session.dataList).shift();
    }
    req.session.transferred++;
    var msg = 'pageSize=' + req.session.pageSize
      + '; pages sent=' + req.session.transferred + '; records remained=' + req.session.dataList.length;
    if(debug) console.log(msg);
    // let commentCount = req.session.commentCount;
    // dataListArray.count = commentCount;
    if(Number(req.session.dataList.length) > 0){
      res.json({errorCode: 1, message: msg, data: dataListArray});
      // res.json({ errorCode: 1, message: msg, commentCount: commentCount, data: dataListArray });
    }
    else {
      if(debug) console.log(msg + '\tno more data left');
      res.json({errorCode: 1, message: msg, data: dataListArray});
      // res.json({ errorCode: 1, message: msg, commentCount: commentCount, data: dataListArray });
      // req.session.destroy();
    }
  } catch(e) {
    res.status(500).send({errorCode: 5, message: e.message});
    // req.session.destroy();
  }
}

/**
 * 以前的是全部整理完成，只要发送。new的却是要动态完成一定的操作。所以是Promises才可以
 * 参考 findAllResources_new，返回值是 theResourceList
 * @param session
 * @returns {Promise<any>}
 */
function getDataPage_new(session, resourceModel) {
  return new Promise(function(resolve, reject) {
    let dataListArray = [];
    let msg = 'session expired';
    if(!session){
      console.error('err8086::session is empty');
      return reject(msg);
    }
    var lastIndex =
      (Number(session.pageSize) <= Number(session.dataList.length)) ? session.pageSize : session.dataList.length;
    for(let i = 0; i < lastIndex; i++) {
      dataListArray.push(session.dataList[i]);
    }
    for(var i = 0; i < lastIndex; i++) {
      (session.dataList).shift()
    }
    session.transferred++;
    msg = 'pageSize=' + session.pageSize
      + '; pages sent=' + session.transferred + '; records remained=' + session.dataList.length;
    //开始获得动态数据
    // setRetDataArray_new(dataListArray, resourceModel, session.me)
    setRetDataArray_1(dataListArray, resourceModel, session.me)//修改了getcommentlist 中的creator
      .then(dataListArray => {
        resolve({message: msg, data: dataListArray});
      }).catch(err => {
      reject(err.message);
    })
    //完成动态数据获得
  }).catch(e => {
    console.error(e)
  })
}

/**
 * get a page of data from session, and reduce the session.dataList
 * @param session
 * @return {{message: string, data: Array}}
 */
function getDataPage(session) {
  let dataListArray = [];
  let msg = 'empty session';
  if(!session){
    console.error('session is empty');
    return {message: msg, data: dataListArray}
  }
  try {
    // var dataList = session.dataList;
    var lastIndex =
      (Number(session.pageSize) <= Number(session.dataList.length)) ? session.pageSize : session.dataList.length;
    for(let i = 0; i < lastIndex; i++) {
      dataListArray.push(session.dataList[i]);
    }
    for(var i = 0; i < lastIndex; i++) {
      (session.dataList).shift()
    }
    session.transferred++;
    msg = 'pageSize=' + session.pageSize
      + '; pages sent=' + session.transferred + '; records remained=' + session.dataList.length;
    return {message: msg, data: dataListArray}
  } catch(e) {
    console.error(e);
  }
}

//删除评论以及子评论
function deleteComment(req, res) {
  try {
    Comment.findOne({commentId: req.body.commentId})
      .exec()
      .then(theComment => {
        if(!theComment){
          return res.json({errorCode: 0, message: 'not comment found'})
        }
        var _commentId = theComment.commentId;
        var _resourceId = theComment.resourceId;
        var findCommentList = commentsbyResourceId(_resourceId);
        assert.ok(findCommentList instanceof Promise);
        var resourceType;
        if(_commentId.indexOf('moment') == 0){
          resourceType = 'moment'
        }
        else if(_commentId.indexOf('video') == 0){
          resourceType = 'video'
        }
        else console.error('wrong commentId or old naming')

        var findResources = resourceFind(resourceType, _resourceId);
        assert.ok(findResources instanceof Promise);
        Promise.all([findCommentList, findResources]).then( function(values) {
          var allComments = values[0];
          var theResource = values[1];
          if(!theResource){
            throw 'For resourceType=' + resourceType + ', no resource found by id=' + _resourceId;
          }
          //检查若是子（二级）评论，1）删除本身。2）更新父节点的childrenIds列表
          //若是一级评论1）更新资源表中childrIds列表。2）删除本身。3）“递归”删除子节点
          // var comments = allComments;
          //更新资源表中childrIds列表。
          var ind = theResource.comments.indexOf(req.body.commentId);
          if(ind >= 0){
            // cmtlist.splice(ind, 1);
            theResource.comments.splice(ind, 1);
            var r = theResource.save();
            assert.ok(r instanceof Promise);
            r.catch(err => {
              console.error('err404' + err.message);
            })
          }
          //更新父节点的childrenIds列表
          if(theComment.parentId){
            for(let i = 0; i < allComments.length; i++) {
              let ind = allComments[i].childrenIds.indexOf(theComment.parentId);
              if(ind >= 0){
                allComments[i].childrenIds.splice(ind, 1);
                var _comment = new Comment({});
                utils.objCopy(allComments[i], _comment);
                if(_comment){
                  var cc = _comment.save();
                  assert.ok(cc instanceof Promise);
                  cc.catch(err => {
                    console.error(err.message);
                  })
                }
                break;
              }
            }
          }
          //删除当前评论和它的子评论
          var comment2del_IdList = [];
          getCommentIds_recursively(theComment);
          if(debug) console.log(comment2del_IdList);
          // await deleteComment(comment2del_IdList);
          deleteComment(comment2del_IdList);
          res.json({
            errorCode: 1,
            message: 'comment @id=' + req.body.commentId + ' and all childrens deleted. total=' + comment2del_IdList.length
          })

          function deleteComment(commentIdList) {
            if(commentIdList.length > 0){
              asyncMethod.each(commentIdList, function(cmtId, callback) {
                Comment.deleteOne({commentId: cmtId})
                  .exec()
                  .then(doc => {
                    if(debug) console.log('deleted: %s=', cmtId)
                    callback(null);
                  }).catch(err => {
                  console.error(err);
                  callback(null)
                })
              }, function(err) {
                if(err){
                  console.error('err405' + err.message)
                }
              });
            }
          }

          function getCommentIds_recursively(comment) {
            comment2del_IdList.push(comment.commentId);
            if(comment.childrenIds.length > 0){
              var childCommentList = getSubComments(comment);
              childCommentList.forEach(ch => {
                getCommentIds_recursively(ch);
              })
            }

            function getSubComments(comment) {
              var retChilds = [];
              allComments.forEach(c => {
                if(comment.childrenIds.indexOf(c.commentId) >= 0){
                  retChilds.push(c);
                }
              })
              return retChilds;
            }
          }
        }).catch(err => {
          console.error(err);
          res.json({errorCode: 0, message: err.message ? err.message : err})
        })
      });
  } catch(e) {
    res.status(500).send({errorCode: 5, message: e.message});
    req.session.destroy();
  }
  finally {

  }
}

/**
 * Trying to check all the conditions.
 * There's the protocals
 * 1, pageSize should not changed for one session
 * 2, pageIndex == 0 means the new session started
 * @param req
 * @param error
 * @return {boolean|*}
 */
function checkGetListCondition(req, error) {
  /*if (Number(req.body.pageIndex) == 0) console.error('new session started:::%s', req.session.id);
  if (req.body.timestamp && req.body.timestamp != req.session.timestamp) console.error('timestamp changed');
  if (req.session.pageSize != req.body.pageSize) console.error('pageSize changed');
  // if(!theSession){
  //   return res.json({errorCode: 0, message: 'the pageIndex==0 but session is empty'})
  // }
  */
  return (!req.session || !req.session.dataList || Number(req.body.pageIndex) === 0
    || (req.body.timestamp && req.body.timestamp != req.session.timestamp))
}

function deletePhotos(photoArray, onS3) {
  //not implemented
}

function deleteFiles(uri, onS3) {
  //not implemented
}

function initSession(req, dataArray) {
  req.session.total = dataArray.length;
  req.session.transferred = 0;
  req.session.dataList = dataArray;
  req.session.timestamp = req.body.timestamp ? req.body.timestamp : Date.now();
  req.session.pageSize = ((Number(req.body.pageSize) < dataArray.length)) ? req.body.pageSize : dataArray.length;
  req.session.expires = Date.now() + 60 * 60 * 1000;
}

function setSession(session, sessionName, input, expires) {
  try {
    let _expires = expires || Date.now() + 60 * 60 * 1000;
    return session[sessionName] = {
      total: input.dataList.length,
      transferred: 0,
      dataList: input.dataList,
      timestamp: input.timestamp ? Number(input.timestamp) : Date.now(),
      pageIndex: Number(input.pageIndex),
      pageSize: ((Number(input.pageSize) < input.dataList.length)) ? input.pageSize : input.dataList.length,
      expires: (input.expires) ? Number(input.expires) : _expires
    }
  } catch(error) {
    console.error(error)
  }
}


function findCreator_by_resourceId(resourceModel, resourceId) {
  return new Promise(function(resolve, reject) { // 99999
    resourceModel.findOne({resourceId: resourceId}).exec()
      .then(function(theResource) { // 找到指定的视频

        if(!theResource){
          return resolve([]);
        }

        var userCode = theResource.userCode;
        resolve(userFind_userCode(userCode)); // 将视频的creator返回出去

      }).catch(err => {
      console.error(err);
    }).catch(err => {
      console.error(err);
    })
  })
}

function isLike(theResource, user) {
  try {
    return (theResource.likes.indexOf(user.userCode) > -1);
  } catch(e) {
  }
  return false;
}

function isLike_v1127(m_resource, user) {
  if(!m_resource || !user) return false;
  try {
    return (m_resource.get('likes').indexOf(user.userCode) > -1);
  } catch(e) {
    console.error(e)
  }
  return false;
}

var isFavourite = function(resource, user) {
  try {
    return utils.inList(user.favourites, resource.resourceId);
  } catch(e) {
  }
  return false;
}
var isFavourite_v1127 = function(m_resource, user) {
  if(!m_resource || !user) return false;
  try {
    return utils.inList(user.favourites, m_resource.get('resourceId'));
  } catch(e) {
  }
  return false;
}

/**
 * resourceModel  可以是viewVideo或者viewMoment
 * me 可能是空（listType=3) ，user不能为空
 * 需要分别过滤。public, follower, private
 * @param resourceModel
 * @param me 发起人
 * @param user 获取资源的对象
 * @returns {Promise<any>}
 */
function findResources(resourceModel, me, user) {
  return new Promise(function(resolve, reject) {
    var giftAmount_user = 0;
    var retDataArray = [];
    let condition = (user) ? {
      "userCode": user.userCode,
      deleted: {$ne: true}
    } : {
      deleted: {$ne: true}
    }

    resourceModel.find(condition).sort({"uploadTime": -1}).limit(10000).exec()
      .then(theResourceList => {
        if(!theResourceList || theResourceList.length <= 0){
          resolve([])
        }
        if(debug){
          console.log('model name::%s; list length=%s', resourceModel.modelName, theResourceList.length);
        }
        theResourceList.forEach(obj => {
            var theResource = JSON.parse(JSON.stringify(obj));
            var m_resouce = Map(theResource);
            let theUser = (user) ? user : m_resouce.get('owner')[0];
            if(checkPermision_v1128(m_resouce, theUser, me)){
              var ret_data = {
                resourceId: m_resouce.get('resourceId'),
                uploadTime: m_resouce.get('uploadTime'),
                lat: m_resouce.get('lat'),
                lon: m_resouce.get('lon'),
                permission: m_resouce.get('permission'),
                likeCount: m_resouce.get('likes').length,
                //so far there's only video has the feature, so just leave it as 0 for moment posted
                favouriteCount: (m_resouce.get('favourites')) ? m_resouce.get('favourites').length : 0,
                isMyLike: isLike_v1127(m_resouce, me),
                isMyFavourite: isFavourite_v1127(m_resouce, me)
              }
              ret_data.creator = getCreator_nopromise_v1128(theUser, me);

              ret_data.giftReceivedTotal = giftReceivedTotal(m_resouce);
              giftAmount_user += ret_data.giftReceivedTotal;

              if(resourceModel.modelName.toLocaleLowerCase().indexOf('moment') >= 0){
                ret_data.photoArray = m_resouce.get('photoArray');
                ret_data.body = m_resouce.get('body');
                ret_data.type = m_resouce.get('type');
              }
              else if(resourceModel.modelName.toLocaleLowerCase().indexOf('video') >= 0){
                ret_data.preview = m_resouce.get('preview');
                ret_data.resourceUri = m_resouce.get('resourceUri');
                ret_data.title = m_resouce.get('title');
                ret_data.description = m_resouce.get('description');
                ret_data.category = m_resouce.get('category');
                ret_data.description = m_resouce.get('description');
              }
              // let c = getCommentlist_nopromise_v1127(m_resouce);
              ret_data.comments = getCommentlist_nopromise_v1127(m_resouce);
              ret_data.commentCount = ret_data.comments.length;
              retDataArray.push(ret_data);
            }
            else {
              console.error('the resource been filtered. resourceId=%s', m_resouce.get('resourceId'))
              if(!theUser) console.log('resource owner not exists:%s', theResource.userCode);
              else if(!theUser.follower || theUser.follower.length <= 0)
                console.log('permission of the resource @resourceId=%s is \'follower\' but owner \;%s\; has follower.', theResource.resourceId, theUser.userCode);
            }
          }
        )

        /*//应该不需要？
        retDataArray.sort(function(a, b) {
          return Number(b.uploadTime) - Number(a.uploadTime);
        });*/

        resolve(retDataArray);
      }).catch(err => {
      console.error(err);
      reject(err.message)
    })
  }).catch(err => {
    console.error(err);
  })
}

/*
function getResourceData(theResource) {
  return {
    resourceId: theResource.resourceId,
    uploadTime: theResource.uploadTime,
    lat: theResource.lat,
    lon: theResource.lon,
    permission: theResource.permission,
    likeCount: (theResource.likes) ? theResource.likes.length : 0,
    favouriteCount: (theResource.favourites) ? theResource.favourites.length : 0
  };
}
*/
function resourceData_new(theResource, resourceModel, me) {
  let ret_resourceData = {
    resourceId: theResource.resourceId,
    uploadTime: theResource.uploadTime,
    lat: theResource.lat,
    lon: theResource.lon,
    permission: theResource.permission,
    likeCount: (theResource.likes) ? theResource.likes.length : 0,
    favouriteCount: (theResource.favourites) ? theResource.favourites.length : 0,
    giftReceived: theResource.amount,
    isMyLike: isLike(theResource, me),
    isMyFavourite: isFavourite(theResource, me)
  };
  if(resourceModel.modelName == 'momentResource'){
    ret_resourceData.photoArray = theResource.photoArray;
    ret_resourceData.body = theResource.body;
    ret_resourceData.type = theResource.type;
  }
  else if(resourceModel.modelName == 'videoResource'){
    ret_resourceData.preview = theResource.preview;
    ret_resourceData.resourceUri = theResource.resourceUri;
    ret_resourceData.title = theResource.title;
    ret_resourceData.description = theResource.description;
    ret_resourceData.category = theResource.category;
    ret_resourceData.description = theResource.description;
  }
  return ret_resourceData;
}

function getExtResourceData(modelName, theResource, ret_data) {
  try {
    if(modelName == 'momentResource'){
      ret_data.photoArray = theResource.photoArray;
      ret_data.body = theResource.body;
      ret_data.type = theResource.type;
    }
    else if(modelName == 'videoResource'){
      ret_data.preview = theResource.preview;
      ret_data.resourceUri = theResource.resourceUri;
      ret_data.title = theResource.title;
      ret_data.description = theResource.description;
      ret_data.category = theResource.category;
      ret_data.description = theResource.description;
    }
    //else throw 'get ext resource data:wrong'
  } catch(e) {
    console.error(e)
  }
}

function getExtResourceData1(resourceModel, ret_data, theResource) {
  try {
    if(resourceModel.modelName == 'momentResource'){
      ret_data.photoArray = theResource.photoArray;
      ret_data.body = theResource.body;
      ret_data.type = theResource.type;
    }
    else if(resourceModel.modelName == 'videoResource'){
      ret_data.preview = theResource.preview;
      ret_data.resourceUri = theResource.resourceUri;
      ret_data.title = theResource.title;
      ret_data.description = theResource.description;
      ret_data.category = theResource.category;
      ret_data.description = theResource.description;
    }
  } catch(e) {
    console.error(e)
  }
}

function checkPermision_v1128(m_resource, theUser, me) {
  let retval = false;
  let msg = 'the resourceId=%s, has been filterred';
  try {
    //keep the sequence
    if(!theUser || !theUser.isEnabled){
      msg = 'err4901: no owner of the resource for resourceId=';
      return false;
    }
    if(m_resource.get('permission') == 'public') retval = true;
    else if(me){
      if(theUser.userCode == me.userCode) retval = true;
      else if(theUser.userCode != me.userCode && m_resource.get('permission') != 'private') retval = true;
      else if(m_resource.get('permission') == 'follower' && theUser.follower.indexOf(me.userCode) >= 0) retval = true;
    }

    if(me && me.blocked && me.blocked.indexOf(theUser.userCode) >= 0){
      // console.log('如果在黑名单里，无论resource是什么权限，都无法看到')
      console.log('my blocked list include the userCode::%s', theUser.userCode)
      retval = false; //
    }
    //这段获取之时已经过滤
    /*if(m_resource.get('deleted') && m_resource.get('deleted') == true){
      console.log('NOTE: this deleted resource will not be displayed:' + m_resource.get('resourceId'));
      retval = false;
    }*/
  }
  catch(e) {
    console.error(e)
  }
  if(debug && !retval){
    console.log(msg, m_resource.get('resourceId'))
  }
  return isTest ? true : retval;
}

function checkPermision(theUser, theResource, me) {
//return true;
  let retval = false;
  let msg = 'the resourceId=%s, has been filterred';
  try {
    //keep the sequence
    if(!theUser || !theUser.isEnabled){
      msg = 'err4901: no owner of the resource for resourceId=';
      return false;
    }
    if(theResource.permission == 'public') retval = true;
    else if(me){
      if(theUser.userCode == me.userCode) retval = true;
      else if(theUser.userCode != me.userCode && theResource.permission != 'private') retval = true;
      else if(theResource.permission == 'follower' && theUser.follower.indexOf(me.userCode) >= 0) retval = true;
    }

    if(me && me.blocked && me.blocked.indexOf(theUser.userCode) >= 0){
      // console.log('如果在黑名单里，无论resource是什么权限，都无法看到')
      console.log('my blocked list include the userCode::%s', theUser.userCode)
      retval = false; //
    }

    if(theResource.deleted && theResource.deleted == true){
      console.log('NOTE: this deleted resource will not be displayed:' + theResource.resourceId);
      retval = false;
    }
    //   retval = false; // 如果在黑名单里，无论resource是什么权限，都无法看到
    // // if(theUser.blocked.indexOf(me.userCode) >= 0) retval = false; // 如果在黑名单里，无论resource是什么权限，都无法看到
  }
  catch(e) {
    console.error(e)
  }
  if(debug && !retval){
    console.log(msg, theResource.resourceId)
  }
  return isTest ? true : retval;
}

function checkPermision1024(theUser, theResource, me) {
  return theUser
    && (theResource.permission == 'public' ||
      (me && typeof me != 'undefined'
        && (me.userCode == theUser.userCode
          || (theResource.permission == 'follower'
            && theUser.follower.length > 0
            && theUser.follower.indexOf(me.userCode) >= 0))));
}

function findAllResources(resourceModel, me) {
  return new Promise(function(resolve, reject) {
    resourceModel.find({
      userCode: theUser.userCode,
      deleted: {$ne: true}
    }).sort({"uploadTime": -1}).exec()
    resourceModel.find().sort({"uploadTime": -1}).exec()
      .then(function(theResourceList) {
        if(!theResourceList || theResourceList.length <= 0){
          return resolve([])
        }
        // theResourceList.reverse();
        var retDataArray = [];
        asyncMethod.each(theResourceList, function(theResource, callback) {
          var userCode = theResource.userCode;
          User.findOne({userCode: userCode}).exec()
            .then(function(theUser) {
              if(checkPermision(theUser, theResource, me)){
                var commentArray = getCommentlist(theResource.resourceId, undefined);
                var ret_data = resourceData(theResource);
                getExtResourceData(resourceModel.modelName, theResource, ret_data);
                ret_data.isMyLike = isLike(theResource, me);
                ret_data.giftReceived = theResource.amount;
                let findcreator = theUser.getCreator_nopromise();

                Promise.all([commentArray, findcreator]).then(function(values) {
                  ret_data.comments = values[0];
                  let c = values[1];
                  c.followship = followship(me, theUser);
                  ret_data.creator = c;
                  retDataArray.push(ret_data);
                  callback(null)
                }).catch(err => {
                  reject(err.message);
                })

              }
              else {
                if(false && debug){
                  console.error('the resource been filtered. resourceId=%s', theResource.resourceId)
                  if(!theUser) console.log('resource owner not exists:%s', theResource.userCode);
                  else if(!theUser.follower || theUser.follower.length <= 0)
                    console.log('permission of the resource @resourceId=%s is \'follower\' but owner \;%s\; has follower.', theResource.resourceId, theUser.userCode);
                }
                callback(null)
              }
            }).catch(err => {
            console.error(err);
            reject(err.message);
          })
        }, function(err) {
          //所有的异步成功执行完成，err等于null
          if(err){
            console.error(err);
            reject(err.message);
          }
          else {
            retDataArray.sort(function(a, b) {
              return Number(b.uploadTime) - Number(a.uploadTime);
            });
            resolve(retDataArray)
          }
        })
      }).catch(err => {
      console.error(err);
      return res.json({errorCode: 0, message: err.message ? err.message : err})
    })
  })

}

function findResources_new(resourceModel, userCode) {
  return new Promise(function(resolve, reject) {
    let condition = (userCode) ? {"userCode": userCode, deleted: {$ne: true}} : {};
    resourceModel.find(condition).sort({"uploadTime": -1}).exec()
      .then(function(theResourceList) {
        resolve(theResourceList)
      }).catch()
  }).catch(err => {
    console.error(err);
  })
}

function findAllResources_new(resourceModel) {
  return new Promise(function(resolve, reject) {
    resourceModel.find()
      .sort({"uploadTime": -1})
      .exec()
      .then(function(theResourceList) {
        // if(!theResourceList || theResourceList.length <= 0){
        //   return resolve([])
        // }
        resolve(theResourceList)
      }).catch(err => {
      console.error(err);
      //return res.json({ errorCode: 0, message: err.message ? err.message : err })
    })
  })
}

function getResourceModel(resourceId) {
  const Moment = model.momentResource;
  const Video = model.videoResource;
  var resourceModel, Resource;
  if(!resourceId) return undefined;
  if(resourceId.indexOf('moment') == 0){
    resourceModel = 'moment';
    Resource = Moment;
  }
  else if(resourceId.indexOf('video') == 0){
    resourceModel = 'video';
    Resource = Video;
  }
  return resourceModel;
}

function getCreator(user) {
  return new Promise(function(resolve, reject) {
    if(!user){
      return user;
    }
    let c = {
      nickName: user.nickName,
      name: user.name,
      userCode: user.userCode,
      avatar: user.avatar,
      followingCount: user.following.length,
      followerCount: user.follower.length
    }
    let findvideo = Video.countDocuments({userCode: user.userCode}).exec();
    assert.ok(findvideo instanceof Promise);
    let findmoment = Moment.countDocuments({userCode: user.userCode}).exec();
    assert.ok(findmoment instanceof Promise);
    Promise.all([findvideo, findmoment]).then(value => {
      c.videoCount = Number(value[0]);
      c.momentCount = Number(value[1]);
      user.momentCount++;
      user.videoCount++;
      user.save();
      resolve();
    }).catch(err => {
      console.error(err);
    })
  })
}

function setCount(user) {
  return new Promise(function(resolve, reject) {
    let findvideo = Video.countDocuments({userCode: user.userCode}).exec();
    assert.ok(findvideo instanceof Promise);
    let findmoment = Moment.countDocuments({userCode: user.userCode}).exec();
    assert.ok(findmoment instanceof Promise);
    Promise.all([findvideo, findmoment]).then(value => {
      let videoCount = Number(value[0]),
        momentCount = Number(value[1]);
      user.videoCount = videoCount + 1;
      user.momentCount = momentCount + 1;
      user.save();
      resolve({videoCount: Number(value[0]) + 1, momentCount: Number(value[1]) + 1});
    }).catch(err => {
      console.error(err);
    })
  }).catch(err => {
    console.error(err);
  })
}

function setCount_promise(resourceModel, user) {
  return new Promise(function(resolve, reject) {
    resourceModel.countDocuments({userCode: user.userCode}).exec()
      .then(theCount => {
        let count = Number(theCount);
        if(getResourceModel(theResource.resourceId) == 'video')
          user.videoCount = count + 1;
        else if(getResourceModel(theResource.resourceId) == 'moment')
          user.momentCount = momentCount + 1;

        user.save();
        resolve();

      }).catch(err => {
      console.error(err);
    })
  })
}

var resourceType = (value => {
  if(value.toLowerCase.indexOf('video')) return 'video';
  if(value.toLowerCase.indexOf('moment')) return 'moment';
  return undefined;
})

function userProfileData_nopromise(user) {
  // return new Promise(function(resolve, reject) {
  if(!user){
    return user;
  }
  return {
    "roleType": user.roleType,
    "countryCode": user.countryCode,
    "gender": user.gender,
    "accountType": user.accountType,
    "mobile": user.mobile,
    "name": user.name,
    "nickName": user.nickName,
    "avatar": user.avatar,
    "userCode": user.userCode,
    "logintime": user.logintime,
    "region": user.region,
    "birthday": user.birthday ? user.birthday : 0,
    "whatsup": user.whatsup,
    "giftsReceived": user.amount,
    "followingCount": user.following.length,
    "followerCount": user.follower.length,
    "interests": user.interests,
    "coverImage": user.publishedResources.coverImage,
    "category": user.publishedResources.category,
    "description": user.publishedResources.description,
    "videoCount": user.videoCount,
    "momentCount": user.momentCount,
    "followship": false
    //"giftsReceived": user.giftsReceived,
    //"giftsSent": user.giftsSent
  }
}

function userProfileData(user) {
  return new Promise(function(resolve, reject) {
    if(!user){
      return user;
    }
    let profile = {
      "roleType": user.roleType,
      "countryCode": user.countryCode,
      "gender": user.gender,
      "accountType": user.accountType,
      "mobile": user.mobile,
      "name": user.name,
      "nickName": user.nickName,
      "avatar": user.avatar,
      "userCode": user.userCode,
      "logintime": user.logintime,
      "region": user.region,
      "birthday": user.birthday ? user.birthday : 0,
      "whatsup": user.whatsup,
      "giftsReceived": user.amount,
      "followingCount": user.following.length,
      "followerCount": user.follower.length,
      "interests": user.interests,
      "coverImage": user.publishedResources.coverImage,
      "category": user.publishedResources.category,
      "description": user.publishedResources.description
      //"giftsReceived": user.giftsReceived,
      //"giftsSent": user.giftsSent
    }
    let findvideo = Video.countDocuments({userCode: user.userCode}).exec();
    assert.ok(findvideo instanceof Promise);
    let findmoment = Moment.countDocuments({userCode: user.userCode}).exec();
    assert.ok(findmoment instanceof Promise);
    Promise.all([findvideo, findmoment]).then(value => {
      profile.videoCount = value[0];
      profile.momentCount = value[1];
      resolve(profile);
    }).catch(err => {
      console.error(err);
    })
  })
}

function userProfileData_new(user, me) {
  return new Promise(function(resolve, reject) {
    if(!user){
      return user;
    }
    return {
      "roleType": user.roleType,
      "countryCode": user.countryCode,
      "gender": user.gender,
      "accountType": user.accountType,
      "mobile": user.mobile,
      "name": user.name,
      "nickName": user.nickName,
      "avatar": user.avatar,
      "userCode": user.userCode,
      "logintime": user.logintime,
      "region": user.region,
      "birthday": user.birthday ? user.birthday : 0,
      "whatsup": user.whatsup,
      "giftsReceived": user.amount,
      "followingCount": user.following.length,
      "followerCount": user.follower.length,
      "interests": user.interests,
      "coverImage": user.publishedResources.coverImage,
      "category": user.publishedResources.category,
      "description": user.publishedResources.description,
      "videoCount": user.videoCount,
      "momentCount": user.momentCount,
      "followership": followship(me, user)
      //"giftsReceived": user.giftsReceived,
      //"giftsSent": user.giftsSent
    }
  })
}

function getCreator_nopromise(user, me) {
  if(!user){
    return user;
  }
  return {
    nickName: user.nickName,
    name: user.name,
    userCode: user.userCode,
    avatar: user.avatar,
    followingCount: user.following.length,
    followerCount: user.follower.length,
    videoCount: user.videoCount ? user.videoCount : 0,
    momentCount: user.momentCount ? user.momentCount : 0,
    followship: followship(me, user),
    blocked: blocked(me, user),

  }
}

function getCreator_nopromise_v1128(user, me) {
  if(!user){
    return {};
  }
  var _user = JSON.parse(JSON.stringify(user));
  /*var data = {
    nickName: _user.nickName,
    name: _user.name,
    userCode: _user.userCode,
    avatar: _user.avatar,
    // followingCount: _user.following.length,
    // followerCount: _user.follower.length,
    videoCount: _user.videoCount ? _user.videoCount : 0,
    momentCount: _user.momentCount ? _user.momentCount : 0,
    followship: followship(me, _user),
    blacked: blocked(me, _user)
  }*/
  return {
    nickName: _user.nickName,
    name: _user.name,
    userCode: _user.userCode,
    avatar: _user.avatar,
    // followingCount: _user.following.length,
    // followerCount: _user.follower.length,
    videoCount: _user.videoCount ? _user.videoCount : 0,
    momentCount: _user.momentCount ? _user.momentCount : 0,
    followship: followship(me, _user),
    blacked: blocked(me, _user)
  };
}

/**
 *
 * @param {Map} me
 * @param {Map} user
 */
var blocked = (me, user) => {
  try {
    return (me.get('blacked').indexOf(user.get('userCode')) >= 0)
  } catch(error) {
  }
  return false;
}
/**
 *
 * @param {userSchema} me
 * @param {userSchema} user
 */
var blocked_v1202 = (me, user) => {
  try {
    return (me.blacked.indexOf(user.userCode) >= 0)
  } catch(error) {
  }
  return false;
}

/**
 *
 * @param {userSchema} me
 * @param {userSchema} user
 */
function followship(me, user) {
  let retval = 0;
  try {
    if(me.following.indexOf(user.userCode) >= 0){
      if(me.follower.indexOf(user.userCode) >= 0) retval = 3;
      else retval = 1
    }
    else if(me.follower.indexOf(user.userCode) >= 0) retval = 2;
  } catch(error) {
  }
  return retval;
}

/**
 *
 * @param {Map} me
 * @param {Map} user
 */
function followship_v1202(me, user) {
  let retval = 0;
  try {
    if(me.get('following').indexOf(user.get('userCode')) >= 0){
      if(me.get('following').indexOf(user.get('userCode')) >= 0) retval = 3;
      else retval = 1
    }
    else if(me.get('follower').indexOf(user.get('userCode')) >= 0) retval = 2;
  } catch(error) {
  }
  return retval;
}

function getAllLists(theSession, resourceModel, sessionName, req) {
  return new Promise(function(resolve, reject) {
    userFind_token_userCode(req.body.token, req.body.userCode)
      .then(me => {
        findAllResources_new(resourceModel, me)
          .then(theResourceList => {
            theResourceList.sort(function(a, b) {
              return Number(b.uploadTime) - Number(a.uploadTime);
            });
            theSession = setSession(req.session, sessionName,
              {
                pageIndex: req.body.pageIndex,
                pageSize: req.body.pageSize,
                resourceModel: resourceModel,
                dataList: theResourceList,
                me: me
              });
            resolve()
          }).catch(err => {
          console.error(err);
          reject(err.message)
        })
      })
  }).catch(e => {
    console.error(e)
  })
}

function getUserCodeResourceIdList(theResourceList, userCode) {
  for(let i in theResourceList) {
    if(theResourceList[i] == userCode)
      return theResourceList[i];
  }
  return undefined;
}

function getUserCodes(theResourceList) {
  var userCodeList = [];
  theResourceList.forEach(r => {
    userCodeList.push(r.userCode);
  });
  return userCodeList;
}

function getUserResourceIds(theResourceList) {
  var userCodeList = [];
  theResourceList.forEach(r => {
    userCodeList.push(r.resourceId);
  });
  return userCodeList;
}

function setRetDataArray_1(theResourceList, resourceModel, me) {
  return new Promise(function(resolve, reject) {
    var retDataArray = [];
    asyncMethod.each(theResourceList, function(theResource, callback) {
      User.findOne({userCode: theResource.userCode}).exec()
        .then(theUser => {
          if(checkPermision(theUser, theResource, me)){
            var retData = resourceData_new(theResource, resourceModel, me);
            retData.creator = getCreator_nopromise_v1128(theUser, me);
            //与原相比只修改了此句。增加了creator的user object
            getCommentlist(theResource.resourceId)
            // getCommentlist_new(theUser, theResource.resourceId)
            // getCommentlist_new({creator: theUser, resourceId: theResource.resourceId})
              .then(function(comments) {
                retData.comments = comments;
                retData.commentCount = comments.length;
                retDataArray.push(retData);
              }).catch(err => {
              console.error(err)
            }).finally(f => {
              callback(null);
            })
          }
          else {
            if(debug){
              console.error('the resource been filtered. resourceId=%s', theResource.resourceId)
              if(!theUser) console.log('resource owner not exists:%s', theResource.userCode);
              else if(!theUser.follower || theUser.follower.length <= 0)
                console.log('permission of the resource @resourceId=%s is \'follower\' but owner \;%s\; has follower.', theResource.resourceId, theUser.userCode);
            }
            callback(null)
          }
        }).catch(err => {
        console.error(err)
      })
    }, function(err) {
      //所有的异步成功执行完成，err等于null
      if(err){
        reject(err.message)
      }
      else {
        retDataArray.sort(function(a, b) {
          return Number(b.uploadTime) - Number(a.uploadTime);
        });
        resolve(retDataArray)
      }
    })
  }).catch(e => {
    console.error(e)
  })
}

const userData = function(user, me, isAppUser) {
  if(!user) return {}
  let userdata = user.getprofile(me);
  // userdata.isAppUser = isAppUser||false;
  return userdata;
  /*return {
    "roleType": user.roleType,
    "countryCode": user.countryCode,
    "gender": user.gender,
    "accountType": user.accountType,
    "mobile": user.mobile,
    "name": user.name,
    "nickName": user.nickName,
    "avatar": user.avatar,
    "userCode": user.userCode,
    "logintime": user.logintime,
    "region": user.region,
    "birthday": user.birthday ? user.birthday : 0,
    "whatsup": user.whatsup,
    "giftsReceived": user.amount,
    "followingCount": user.following.length,
    "followerCount": user.follower.length,
    "interests": user.interests,
    "category": user.publishedResources.category,
    "description": user.publishedResources.description,
    "followship": (me) ? utils.followship(me, user) : 0,
    "isAppUser": (isAppUser) ? isAppUser : false
  }*/
}

function deviceUpdate(devicetoken, platform, token) {
  return new Promise(function(resolve, reject) {
    if(!devicetoken || !platform || !token) reject('incorrect parameters');
    User.updateOne({"token": token},
      {
        "device.devicetoken": devicetoken,
        "device.platform": platform
      }).then(data => {
      if(data.n > 0 && data.nModified > 0){
        if(debug) console.log('device token(%s) updated', devicetoken);
        resolve('devicetoken submited');
      }
      else if(data.n > 0 && data.nModified <= 0)
        resolve('devicetoken not changed');
      else reject('user not found or auth failed');
    }).catch(err => {
      console.error(err);
      reject(err.message)
    })
  })
}

var giftReceivedTotal = function(resourceModelmap) {
  var retval = 0;
  var gifts = resourceModelmap.get('giftsReceived');
  gifts.forEach(g => {
    retval += g.money;
  })
  return retval;
}

/**
 * recursively get the return data for comment
 * it's construct as comment/childs count
 * @param {commentSchema} comment
 * @param {[commentSchema]} allChildComments
 */
function getResData_v1202(comment, allChildComments, me) {
  /**
   * convert the child id list into comment list
   * @param {*} IdList commentId list
   */
  function commentIdstoComments(IdList) {
    let retval = [];
    allChildComments.forEach(c => {
      IdList.forEach(id => {
        if(id == c.commentId){
          retval.push(c);
        }
      })
    })
    return retval;
  }

  if(false && comment.commentId == 'moment-5bfa9ecc69c8b82b3192a947'){
    console.log(comment);
  }
  var retData = [];
  let data = {
    body: comment.body,
    creator: comment.creator,
    postTime: comment.postTime,
    replyTo: comment.replyTo,
    replyToName: comment.replyToName,
    commentId: comment.commentId,
    likeCount: comment.likes.length,
    commentCount: allChildComments.length
  }
  if(comment.owner){
    data.creator = getCreator_nopromise_v1128(comment.owner[0], me);
  }
  if(!comment.childrenIds || comment.childrenIds.length == 0){
    data.comments = [];
  }
  else {
    let childComments = commentIdstoComments(comment.childrenIds);
    let childData = [];
    childComments.forEach(childComment => {
      childData = childData.concat(getResData_v1202(childComment, allChildComments, me));
    })
    data.comments = childData;
  }
  retData.push(data);
  return retData;
}

module.exports = {
  getCommentlist_nopromise_v1127: (m_resouce, commentId) => getCommentlist_nopromise_v1127(m_resouce, commentId),
  userFind: (findbyType, findbyValue) => userFind(findbyType, findbyValue),
  userFind_token_userCode: (token, userCode) => userFind_token_userCode(token, userCode),
  userFind_token_userCode_auth: (token, userCode) => userFind_token_userCode_auth(token, userCode),
  userFind_token: (token) => userFind_token(token),
  userFind_openid: (openid) => userFind_openid(openid),
  userFind_userCode: (userCode) => userFind_userCode(userCode),
  userFind_mobile: (mobile, countryCode) => userFind_mobile(mobile, countryCode),
  userFind_email: (email) => userFind_email(email),
  addressBookUserFind: (userCode) => addressBookUserFind(userCode),
  userAuth: (token) => userAuth(token),
  userFindAuth: (token, userCode) => userFindAuth(token, userCode),
  favouritebyResourceId: (resourceId) => favouritebyResourceId(resourceId),
  momentbyResourceId: (resourceId) => momentbyResourceId(resourceId),
  momentbyUserCode: (userCode) => momentbyUserCode(userCode),
  resourceFind: (resourceType, resourceId) => resourceFind(resourceType, resourceId),
  resourceFind_new: (resourceModel, resourceId) => resourceFind_new(resourceModel, resourceId),
  deviceUpdate: (devicetoken, platform, token) => deviceUpdate(devicetoken, platform, token),
  resourceFind_zl: (resourceId) => resourceFind_zl(resourceId),
  resourcelistFind: (resourceType, resourceId) => resourcelistFind(resourceType, resourceId),
  resourceListbyUserCode: (resourceType, userCode) => resourceListbyUserCode(resourceType, userCode),
  getCommentlist: (resourceId, commentId) => getCommentlist(resourceId, commentId),
  commentFindOne: (commentId) => commentFindOne(commentId),
  commentsbyResourceId: (resourceId) => commentsbyResourceId(resourceId),
  getNetCastData: (user) => getNetCastData(user),
  followingUserList: (me) => followingUserList(me),
  getVideoResourceData: (user, resourceList) => getVideoResourceData(user, resourceList),
  getnetcastResourceData: (followingUserList) => getnetcastResourceData(followingUserList),
  sendListPage: (req, res) => sendListPage(req, res),
  sendListPage_v1126: (session, res) => sendListPage_v1126(session, res),
  getDataPage_new: (session, resourceModel) => getDataPage_new(session, resourceModel),
  getDataPage: (session) => getDataPage(session),
  giftFind_id: (id) => giftFind_id(id),
  checkGetListCondition: (req) => checkGetListCondition(req),
  checkConditions: (conditions) => checkConditions(conditions),
  deleteComment: (req, res) => deleteComment(req, res),
  deletePhotos: (photoArray, onS3) => deletePhotos(photoArray, onS3),
  deleteFiles: (uri, onS3) => s3DeleteFile(uri, onS3),
  initSession: (req, dataArray) => initSession(req, dataArray),
  setSession: (session, sessionName, input) => setSession(session, sessionName, input),
  findResources: (resourceModel, me, theUser) => findResources(resourceModel, me, theUser),
  findResources_new: (resourceModel, userCode) => findResources_new(resourceModel, userCode),
  findAllResources: (resourceModel, me) => findAllResources(resourceModel, me),
  findAllResources_new: (resourceModel) => findAllResources_new(resourceModel),
  getResourceModel: (resourceId) => getResourceModel(resourceId),
  getCreator: (user) => getCreator(user),
  setCount: (user) => setCount(user),
  setCount_promise: (resourceModel, user) => setCount_promise(resourceModel, user),
  getCreator_nopromise: (user, me) => getCreator_nopromise(user, me),
  userProfileData: (user) => userProfileData(user),
  // userProfileData_new: (user, me) => userProfileData_new(user, me),
  userProfileData_nopromise: (user) => userProfileData_nopromise(user),
  getAllLists: (theSession, resourceModel, sessionName, req) => getAllLists(theSession, resourceModel, sessionName, req),
  getResData_v1202: (comment, allChildComments, me) => getResData_v1202(comment, allChildComments, me),
  userData: userData,
  blocked: blocked
}
